#ifndef SOCKET_HPP
#define SOCKET_HPP

#include <sys/types.h>
#include <sys/socket.h>

#include "log.hpp"
#include "Addr.hpp"
using namespace LOG;

enum
{
    Socket_errno = 1,
    Bind_errno,
    Listen_errno
};
//--------------------------------------------------------------------
class SocketFactory // 工厂模式
{
private:
    // 创建套接字
    virtual void Socket() {};
    // 绑定
    virtual void Bind() {};
    // 设置listen状态
    virtual void Listen() {};
    // 获取新连接
    virtual int Accept() {return 0;};
    // 获得套接字
    virtual int GetSocket() {return 0;};

public:
    SocketFactory() {};
    ~SocketFactory() {};
};
//--------------------------------------------------------------------
class UDP_Socket : public SocketFactory
{
private:
    // 创建套接字
    void Socket()
    {
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd < 0)
        {
            lg(FATAL, "Socket fail");
            exit(Socket_errno);
        }
        _sockfd = sockfd;
    }

    // 绑定
    void Bind(class Addr &addr)
    {
        int b = bind(_sockfd, (struct sockaddr *)(&addr), addr.Len());
        if (b < 0)
        {
            lg(FATAL, "Bind fail");
            exit(Bind_errno);
        }
    }

public:
    UDP_Socket(class Addr &addr)
    {
        Socket();
        Bind(addr);
    };

    ~UDP_Socket() {};

    int GetSocket()
    {
        return _sockfd;
    }

private:
    int _sockfd;
};
//--------------------------------------------------------------------
class TCP_Socket : public SocketFactory
{
private:
    // 创建套接字
    void ListenSocket()
    {
        int listensockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (listensockfd < 0)
        {
            lg(FATAL, "Socket fail");
            exit(Socket_errno);
        }
        lg(INFO,"Socket create success");
        _listensockfd = listensockfd;
    }

    // 绑定
    void Bind(class Addr addr)
    {
        int b = bind(_listensockfd,(struct sockaddr *)(&addr), addr.Len());
        if (b < 0)
        {
            lg(FATAL, "Bind fail");
            exit(Bind_errno);
        }
        lg(INFO,"Bind success");
    }

    // 设定监听状态
    void Listen()
    {
        int l = listen(_listensockfd, 12);
        if (l < 0)
        {
            lg(FATAL, "Listen fail");
            exit(Listen_errno);
        }
        lg(INFO,"Set listen success");
    }

public:
    TCP_Socket(class Addr addr)
    {
        ListenSocket();
        Bind(addr);
        Listen();
    };

    ~TCP_Socket() {};

    int GetSocket()
    {
        return _listensockfd;
    }

private:
    int _listensockfd;
};

#endif

